from PIL import Image
import numpy as np
import struct
import random
#移位运算
def demo(lst, k):
    return lst[k:] + lst[:k]

#32字符异或运算
def xor32(x,y):
    n=len(x)
    u=int(x,2)^int(y,2)
    return f'{u:032b}'

#128字符异或运算
def xor128(x,y):
    n=len(x)
    u=int(x,2)^int(y,2)
    return f'{u:0128b}'

#32位与运算
def Yand32(x,y):
    n=len(x)
    u=int(x,2)&int(y,2)
    return f'{u:032b}'

#轮函数F
def F(x,y):
    u=xor32(x,y)
    u1=u[0:8]
    u2=u[8:16]
    u3=u[16:24]
    u4=u[24:32]
    S={'0':5,'1':10,'2':15,'3':4,'4':9,'5':14,'6':11,'7':8,'8':2,'9':7,'10':12,'11':13,'12':3,'13':6,'14':1,'15':0}
    v1=format(S[str(int(u1[0:4],2))],'04b')+format(S[str(int(u1[4:8],2))],'04b')
    v2=format(S[str(int(u2[0:4],2))],'04b')+format(S[str(int(u2[4:8],2))],'04b')
    v3=format(S[str(int(u3[0:4],2))],'04b')+format(S[str(int(u3[4:8],2))],'04b')
    v4=format(S[str(int(u4[0:4],2))],'04b')+format(S[str(int(u4[4:8],2))],'04b')
    v=v1+v2+v3+v4
    z=xor32(xor32(v,demo(v,3)),demo(v,10))
    return z

#密钥扩展算法ExpandKey
def ExpandKey(k):
    kls=list()
    kls.append(k[0:32])
    kls.append(k[32:64])
    kls.append(k[64:96])
    kls.append(k[96:128])
    for i in range(92):
        k0=Yand32(Yand32(xor32(xor32(kls[i],32*'1'),xor32(kls[i+1],32*'1')),kls[i+2]),xor32(kls[i+3],format(i,'032b')))
        k0=xor32(xor32(k0,demo(k0,13)),demo(k0,22))
        kls.append(k0)
    return kls

#加密
def Enc(P,k):
    kls=ExpandKey(k)
    als=list()
    bls=list()
    cls=list()
    dls=list()
    als.append(P[0:32])
    bls.append(P[32:64])
    cls.append(P[64:96])
    dls.append(P[96:128])
    for i in range(47):
        als.append(xor32(F(als[i],kls[2*i]),bls[i]))
        cls.append(xor32(als[i+1],dls[i]))
        dls.append(xor32(F(dls[i],kls[2*i+1]),cls[i]))
        bls.append(xor32(dls[i+1],als[i]))
    bls.append(xor32(F(als[47],kls[94]),bls[47]))
    dls.append(xor32(bls[48],dls[47]))
    cls.append(xor32(F(dls[47],kls[95]),cls[47]))
    als.append(xor32(cls[48],als[47]))
    C=als[48]+bls[48]+cls[48]+dls[48]
    return C

#获取明文P
img=Image.open("金丝猴.bmp")
P_arr=np.array(img)
P=''
Pls=[]
for i in range(1390):
    for j in range(2000):
        for k in range(3):
            Pls.append(int(P_arr[i][j][k]))
for i in range(1390*2000*3):
    P=P+format(Pls[i],'08b')

#获取密钥k
k=''
for i in range(128):
    k=k+str(random.randint(0,1))

#获取初始化向量iv
iv=''
for i in range(128):
    iv=iv+str(random.randint(0,1))

#加密
C=''
C=C+Enc(xor128(P[0:128],iv),k)
for i in range(1,521250):
    C=C+Enc(xor128(P[128*i:128*(i+1)],C[128*(i-1):128*i]),k)
C_arr=np.array(img)
for i in range(1390):
    for j in range(2000):
        for k in range(3):
            C_arr[i][j][k]=int(C[48000*i+24*j+8*k:48000*i+24*j+8*k+8])
arr = np.array(C_arr) 
arr=np.array(arr,dtype='uint8')
arr=Image.fromarray(arr)
arr.save('CBC.bmp','bmp')